开发准备:templates 目录整理 + CLI 调试方法
概述
在开发 CLI 模板生成工具前,需要整理模板项目目录结构,将配置文件改造为 EJS 模板格式,使其支持动态变量替换。同时掌握 CLI 工具的调试方法,包括带 prompts 和带参数两种调试模式。
模板目录结构
目录组织规则
templates/
├── base/ # 基础模板
│ ├── package.json.ejs # EJS 模板文件(动态生成)
│ ├── vite.config.date.ejs # 带日期后缀(避免直接覆盖)
│ ├── tsconfig.json
│ ├── index.html
│ └── src/
│ ├── main.ts.ejs
│ └── App.vue
├── config/ # 配置模板片段
│ ├── router/
│ │ └── index.ts.ejs
│ ├── pinia/
│ │ └── index.ts.ejs
│ └── unocss/
│ └── uno.config.ts.ejs
├── cdn/ # CDN 模板
│ ├── vite.config.date.ejs
│ └── index.html.ejs
└── component/ # 组件模板
└── VpButton/
└── index.vue.ejs
text
文件命名规范
| 后缀 | 含义 | 处理方式 |
|---|---|---|
.ejs | EJS 模板文件 | 通过 CLI 渲染后去掉 .ejs 后缀输出 |
.date.ejs | 带日期标记的模板 | 输出时替换为 .ts / .js |
| 无后缀 | 静态文件 | 直接复制到目标目录 |
EJS 模板语法
基础语法
// vite.config.date.ejs
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
<% if (useRouter) { %>
import router from './router'
<% } %>
<% if (usePinia) { %>
import { createPinia } from 'pinia'
<% } %>
export default defineConfig({
plugins: [
vue()<% if (useRouter) { %>,
router()<% } %>
]<% if (useUnocss) { %>,
css: {
preprocessorOptions: {}
}<% } %>
})
ejs
关键注意事项
| 规则 | 说明 |
|---|---|
| 结尾不加逗号 | EJS 条件块中的最后一项不加尾逗号,避免语法错误 |
| 导入块独立 | imports 部分按功能分组,条件导入用 <% if %> 包裹 |
| 覆盖策略 | 同名文件(如 unocss)通过条件导入覆盖 base 中的默认配置 |
CLI 调试方法
方式一:npm link 全局调试
# 在 CLI 项目中构建并链接
cd create-vue-template
pnpm build
npm link
# 在任意目录中使用
mkdir test-project && cd test-project
create-vue-template
bash
方式二:VS Code 调试配置
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug CLI",
"type": "node",
"request": "launch",
"runtimeExecutable": "node",
"runtimeArgs": ["--import", "tsx", "${workspaceFolder}/index.ts"],
"cwd": "${workspaceFolder}",
"console": "integratedTerminal"
},
{
"name": "Debug CLI with args",
"type": "node",
"request": "launch",
"runtimeExecutable": "node",
"runtimeArgs": ["--import", "tsx", "${workspaceFolder}/index.ts"],
"args": ["--template", "base", "--name", "test-app"],
"cwd": "${workspaceFolder}",
"console": "integratedTerminal"
}
]
}
json
方式三:prompts.inject 注入测试
// __tests__/cli.test.ts
import prompts from 'prompts'
import { createTemplate } from '../src/core'
// 注入预设回答,跳过交互
prompts.inject([
'test-project', // projectName
'base', // template
['router', 'pinia'],// features
true // useTypescript
])
test('CLI 创建基础模板', async () => {
await createTemplate({ projectName: 'test-project' })
// 验证文件是否生成
})
typescript
方式四:node --import tsx 直接运行
# 开发模式下直接运行 TypeScript(无需构建)
node --import tsx index.ts
# 带参数运行
node --import tsx index.ts --template base --name my-app
bash
调试场景对照
| 调试需求 | 推荐方式 | 命令/配置 |
|---|---|---|
| 快速验证功能 | node --import tsx | node --import tsx index.ts |
| 带交互的调试 | VS Code Launch | 配置 launch.json |
| 带参数的调试 | VS Code Launch + args | 在 args 中传参 |
| 自动化测试 | prompts.inject | 注入预设回答 |
| 模拟真实使用 | npm link | 全局链接后使用 |
实践要点
- 模板文件统一使用
.ejs后缀标记,CLI 生成时去掉后缀输出最终文件 - 配置文件(如
vite.config)添加.date标记区分模板和实际输出文件 - EJS 模板中条件块的最后一项不加尾逗号,防止模板渲染时产生语法错误
- 开发调试使用
node --import tsx直接运行 TypeScript,无需每次构建 - 使用
prompts.inject()在测试环境中注入预设回答,跳过交互提示 - VS Code 的
launch.json支持通过args字段传递命令行参数进行调试
↑